package cn.yshujia.service.impl;

import cn.yshujia.domain.dto.PageDTO;
import cn.yshujia.domain.entity.User;
import cn.yshujia.domain.vo.PageVO;
import cn.yshujia.domain.vo.UserVO;
import cn.yshujia.encryption.AESEncrypt;
import cn.yshujia.enums.Info;
import cn.yshujia.ex.DefineExceptionHandler;
import cn.yshujia.mapper.UserMapper;
import cn.yshujia.repository.UserRepository;
import cn.yshujia.utils.IDUtils;
import cn.yshujia.utils.JwtTokenUtils;
import cn.yshujia.utils.PageUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author YShuJia
 * @create 2024/4/23
 * @description 服务层
 */

@Service
@Transactional (rollbackFor = {Exception.class})
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IService<User> {
	
	@Resource
	UserMapper mapper;
	
	@Resource
	UserRepository repository;
	
	@Resource
	BCryptPasswordEncoder passwordEncoder;
	
	public UserVO getUser(Long id) {
		return repository.getUser(id);
	}
	
	public UserVO userInfo(String token) {
		Long userId = JwtTokenUtils.getUserId(token);
		if (null == userId) {
			return null;
		}
		return repository.getUser(userId);
	}
	
	public PageVO<UserVO> adminPage(PageDTO dto) {
		QueryWrapper<User> wrapper = PageUtils.createUserWrapper(dto);
		IPage<User> page = mapper.selectPage(new Page<>(dto.getCurrent(), dto.getSize()), wrapper);
		// 创建VO集合
		if (!ObjectUtils.isEmpty(page) && !ObjectUtils.isEmpty(page.getRecords())) {
			return PageUtils.getPage(dto, repository.createUserList(page.getRecords()), page.getTotal());
		}
		return new PageVO<>();
	}
	
	public Map<String, List<String>> selectCountGroupByRoleId() {
		List<UserVO> list = mapper.selectCountGroupByRoleId();
		List<String> keys = new ArrayList<>();
		List<String> values = new ArrayList<>();
		Map<String, List<String>> map = new HashMap<>();
		list.forEach(item -> {
			keys.add(item.getRole().getName());
			values.add(item.getCount().toString());
		});
		map.put("keys", keys);
		map.put("values", values);
		return map;
	}
	
	@Transactional (rollbackFor = {Exception.class})
	public Boolean insert(String email, String password) throws DefineExceptionHandler {
		// 判断邮箱是否重复
		User old = mapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getEmail, AESEncrypt.encrypt(email)));
		if (old != null) {
			throw new DefineExceptionHandler(Info.HAD_USER.getCode(), Info.HAD_USER.getMessage());
		}
		User user = new User(IDUtils.getId(), "船员", passwordEncoder.encode(password), email, "/comment/20241228/20241228181400183.webp");
		return mapper.insert(user) > 0;
	}
	
	@Transactional (rollbackFor = {Exception.class})
	public Boolean insert(User user) throws DefineExceptionHandler {
		// 判断邮箱是否重复
		User old = mapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getEmail, AESEncrypt.encrypt(user.getEmail())));
		if (old != null) {
			throw new DefineExceptionHandler(Info.HAD_USER.getCode(), Info.HAD_USER.getMessage());
		}
		user.setId(IDUtils.getId());
		// 加密密码
		user.setPassword(passwordEncoder.encode(user.getPassword()));
		user.setAvatar("/comment/20241228/20241228181400183.webp");
		return mapper.insert(user) > 0;
	}
	
	@Transactional (rollbackFor = {Exception.class})
	public Boolean update(User user) {
		if (user.getPassword() != null) {
			user.setPassword(passwordEncoder.encode(user.getPassword()));
		}
		int n = mapper.updateById(user);
		if (n > 0) {
			repository.del();
		}
		return n > 0;
	}
}